/**
 * 
 */
package duckHunter.ui;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.media.MediaException;

import duckHunter.app.ApplicationResource;
import duckHunter.app.GameContext;
import duckHunter.sprites.BallSprite;
import duckHunter.sprites.CanardSprite;
import duckHunter.sprites.GunSprite;



/** Level1 class is a public class the extends the GameCanvas Class 
 * and implements the Runnable interface.
 * it represent the core of the project which contains the game we had developed
 * it creates different sprites and defines their positions 
 * and trajectories according to give values
 * it also listens to user interactions and perform methods according to the keys pressed 
 * 
 * @author AYARI
 */
public class Level1 extends GameCanvas implements Runnable{
	// to generate random integers to vary the trajectory of the bomb sprites
	private Random generator;
	// integer used as the speed of the sprite 
	//initialized to 3
	private int speed =3;
	// boolean attributes to test the state of the gameCanvas
	private volatile boolean mRun;
	private boolean gameOver = false;
	private boolean controlsEnabled = true;
	// layer manager to append the created sprites
	private LayerManager mLayerManager = new LayerManager();
	// Size of one frame in the spiral image
	private static final int FRAME_WIDTH = 32;
	private static final int FRAME_HEIGHT = 32;
	//value of the pressed key by the user
	public int key;
	public Level1 test;
	// images 
	private Image mBackGround;
	private Image mGameOver;
	//vectors to store sprites 
	private Vector balls = new Vector();
	private Vector canards = new Vector();
	private GunSprite gun;
	private CanardSprite canard;
	private BallSprite cartouche;
	//used to iterate a vector
	private Enumeration e;
	//timer used to add an canard sprite
	private Timer timerAddCanard = new Timer();		
	//to play this sound canard
	SoundPlayer canardSound = new SoundPlayer("/audio/canard.wav");
	//to play the fusil sound
	SoundPlayer fusilSound = new SoundPlayer("/audio/fusil.wav");
		/**
	* @return the mLayerManager
	 */
	public LayerManager getmLayerManager() {
		return mLayerManager;
	}
	/**
	 * @param mLayerManager the mLayerManager to set
	 */
	public void setmLayerManager(LayerManager mLayerManager) {
		this.mLayerManager = mLayerManager;
	}
	/**
	 * default constructor
	 * @throws IOException
	 */
	public Level1() throws IOException {
		super(true);
		// Layers and sprite creation
		//create the Gun sprite 
		gun = new GunSprite(ApplicationResource.getImgGun(), FRAME_WIDTH,FRAME_HEIGHT);
		gun.setPosition(85,240);		
		mLayerManager.append(gun);		
		//create the backgroundImage and the gameOverImage
		mBackGround = Image.createImage("/img/background.png");
		mGameOver = Image.createImage("/img/deadPlanet.png");
		//initialize the random generator
		generator = new Random();

	}
	public void start() {
		if(!mRun)
		{
			mRun = true;
			Thread	t= new Thread(this);
			t.start();
		}
		//adding the tasks to the timers and defining the period of every timer
		timerAddCanard.schedule(new AddCanardTask(),3000,3000 );
	}
	// run method from Runnable
	public void run() {
		Graphics g = getGraphics();
		// tests the mRun if true it continues else it do nothing
		while (mRun) {
			update();
			render(g);
			// it sleeps for 20 milliseconds and then continues working
			try {Thread.sleep(20);} catch (InterruptedException e) {System.out.println(e);} 
		}
	} 
	// update game logic 
	private void update() {
		//move the sprites
		int maxW = getWidth();
		int maxH = getHeight();
		//move canards sprites
		Enumeration em = canards.elements();
		while(em.hasMoreElements()) {
			CanardSprite enemy = (CanardSprite) em.nextElement();
			try {
				enemy.moveSprite(maxW, maxH);
			} catch (MediaException e1) {
				e1.printStackTrace();
			}
		}
		//move cartouche sprites
		Enumeration b = balls.elements();
		while(b.hasMoreElements()) {
			BallSprite bs = (BallSprite) b.nextElement();
			try {
				bs.moveSprite(this,maxW+3,maxH+3);
			} catch (MediaException e) {
				e.printStackTrace();
			}
		}
		
		Enumeration cn = canards.elements();
		Enumeration ba = balls.elements();
		while(b.hasMoreElements())	{
		BallSprite bs = (BallSprite) ba.nextElement();
			while(em.hasMoreElements()){
				CanardSprite c=(CanardSprite) cn.nextElement();
				if (bs.collidesWith(c, true))
				{
					GameContext.getInstance().incScore(10);
					this.getmLayerManager().remove(bs);
					this.getmLayerManager().remove(c);
		
				}
			}
		}
		
		
	}


	//task to create canard sprites
	private class AddCanardTask extends TimerTask{

		public void run() {
			addCanard();
		}
	}
	//add a canard sprite
	public void addCanard(int compteur) throws MediaException{
		
		CanardSprite canard = null;
	
		int deltaX = generator.nextInt(speed);
		int deltaY = generator.nextInt(speed);
		while(deltaX==0 || deltaY==0){
			deltaX = generator.nextInt(speed);
			deltaY = generator.nextInt(speed);
		}
		try {
			
			canardSound.play();
		} catch (IOException e) {e.printStackTrace();}
		//we set the bomb either on the canonD side or the canonG side depending on
		//the compteur value
		if(compteur % 2 == 0){
			canard.setPosition(3,80);
		}else{
			canard.setPosition(FRAME_WIDTH-canard.getWidth(),80);
		}

		mLayerManager.append(canard);
		//add the bomb to the bombs vector
		canards.addElement(canard);
	}
	//add an enemy sprite 
	public void addCanard(){
		CanardSprite enemy;
		enemy = new CanardSprite(ApplicationResource.getImgCanard(), FRAME_WIDTH, FRAME_HEIGHT, 2);
		enemy.setPosition(5, 40);
		//add the enemy to the enemies vector
		canards.addElement(enemy);
		mLayerManager.append(enemy);
	}
	public void stop(){
	}
	//painting or drawing the game screen
	private void render(Graphics g) {
		int w = getWidth();
		int h = getHeight();

		g.setColor(0xffffff);
		//fill the screen with a rectangle to remove any drawn or added objects
		g.fillRect(0, 0, w, h);

		//draw the background image
		g.drawImage(mBackGround, 0, 0, Graphics.TOP | Graphics.LEFT);

		g.setColor(0, 0, 0);
		g.fillRect(0, 0, g.getClipWidth(), 20);

		
		//draw the Score on the upper left corner of the screen
		//the score is stored in the GameContext clas
		g.setColor(200, 200, 200);
		g.drawString("Score : " + GameContext.getInstance().getScore(), 0, 0, Graphics.TOP | Graphics.LEFT);

		//if the number of lives is less than 0
		//game over
		if(GameContext.getInstance().getNbCartouche() < 0) {
			controlsEnabled  = false;
			//cancel all the timers
			timerAddCanard.cancel();
			//set mRun to false
			mRun = false;
			//cal gameOver method
			gameOver(g);
		} else {
			// else we draw the number of munition on the upper right corner of the screen
			g.drawString("Munition : " + GameContext.getInstance().getNbCartouche(), g.getClipWidth(), 0, Graphics.TOP | Graphics.RIGHT);
		}
		int x = 0;
		int y = 0;
		//paint the graphics
		mLayerManager.paint(g, x, y);
		flushGraphics();
	}
	// remove all the added sprites 
	//remove all the sprites in the vectors of sprites
	public void gameOver(Graphics g){
		gameOver=true;
		GameContext.getInstance().updateHighScore();
		
		Enumeration cn = canards.elements();
		while(cn.hasMoreElements()) {
			CanardSprite c = (CanardSprite) cn.nextElement();
			this.mLayerManager.remove(c);
		}
		
		
		Enumeration bl = balls.elements();
		while(bl.hasMoreElements()){
			BallSprite b = (BallSprite) bl.nextElement();
			this.mLayerManager.remove(b);
		}
		//paint the gameOver screen
		g.setColor( 0,  0, 0 );
		g.fillRect( 0, 0, getWidth(), getHeight() );
		g.setColor(200, 200, 200);
		g.drawImage(mGameOver, 60,50 , 0);
		g.setStrokeStyle(Graphics.DOTTED);
		g.drawString("Game over, you failed to hunt ducks", g.getClipWidth()-20, g.getClipHeight()/2, Graphics.TOP | Graphics.RIGHT);


	}
	/**
	 * listens to what key is pressed by the user
	 * call methods according to the pressed key
	 */
	protected  void keyPressed(int keyCode) {
		this.key = keyCode;
		//used for testing measures
		System.out.println(keyCode);
		switch(keyCode){
		
		case KEY_NUM4:
			//move the target sprite left
			gun.moveLeft(8);
			render(getGraphics());
			break;
		case KEY_NUM5:
			//call shoot method
			tirer();
			render(getGraphics());
			break;
		case KEY_NUM6:
			//move the target sprite right
			gun.moveRight(8,getWidth());
			render(getGraphics());
			break;		
		default:;
		}
		repaint();
	}
	//called when the fire key is pressed (5)
	public void tirer(){
		if(GameContext.instance.getNbCartouche()>0)
		{
		//Pay cartouche Sound
		playMidi1();
		//create new cartouche sprite
		cartouche = new BallSprite(ApplicationResource.getImgCartouche(), FRAME_WIDTH,FRAME_HEIGHT);
		cartouche.setPosition(gun.getX(),gun.getY());
		//add cartouche sprite in mLayer manager
		mLayerManager.append(cartouche);
		balls.addElement(cartouche);		
	    GameContext.instance.decNBCartouche();
		}
		else
		{
		gameOver=true;
		}
		update();
		
	}
		
	protected  void keyRepeated(int keyCode) {
		keyPressed(keyCode);
	}
	public Sprite getGunSprite() {
		return gun;
	}	
	public void setMRun(boolean state){
		mRun = state;
	}
	/**
	 * @param speed the speed to set
	 */
	public void setSpeed(int speed) {
		this.speed = speed;
	}
	/**
	 * @return the gameOver
	 */
	public boolean isGameOver() {
		return gameOver;
	}
	//play canard sound
	public void playMidi() {

		
		try {
			canardSound.play();

		} catch (IOException e) {
			e.printStackTrace();
		} catch (MediaException e) {
			e.printStackTrace();
		}
	}
	//play cartouche sound
	public void playMidi1() {
		try {
			fusilSound.play();

		} catch (IOException e) {
			e.printStackTrace();
		} catch (MediaException e) {
			e.printStackTrace();
		}
	}
}
